package xyz.zhno.mall.product.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import xyz.zhno.mall.common.core.util.BeanUtils;
import xyz.zhno.mall.common.core.util.CollUtils;
import xyz.zhno.mall.common.core.util.Validator;
import xyz.zhno.mall.common.mpg.entity.PmsProduct;
import xyz.zhno.mall.common.mpg.entity.PmsProductCategory;
import xyz.zhno.mall.common.mpg.entity.PmsProductCategoryAttributeRelation;
import xyz.zhno.mall.common.mpg.mapper.PmsProductCategoryAttributeRelationMapper;
import xyz.zhno.mall.common.mpg.mapper.PmsProductCategoryMapper;
import xyz.zhno.mall.common.mpg.mapper.PmsProductMapper;
import xyz.zhno.mall.product.model.dto.PmsProductCategoryNodeDTO;
import xyz.zhno.mall.product.model.param.PmsProductCategoryParam;
import xyz.zhno.mall.product.web.service.PmsProductCategoryService;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 商品分类业务层实现
 * @author zh_o
 */
@Service
@AllArgsConstructor
public class PmsProductCategoryServiceImpl extends ServiceImpl<PmsProductCategoryMapper, PmsProductCategory> implements PmsProductCategoryService {

    private final PmsProductCategoryAttributeRelationMapper pmsProductCategoryAttributeRelationMapper;

    private final PmsProductMapper pmsProductMapper;

    /**
     * 新增分类
     * @param param 新增分类参数对象
     * @return 新增分类ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long create(PmsProductCategoryParam param) {
        // 拷贝参数值
        PmsProductCategory productCategory = BeanUtils.copyProperties(param, PmsProductCategory.class);
        // 设置数量为0
        productCategory.setProductCount(0);
        // 设置分类等级
        setCategoryLevel(productCategory);
        // 新增数据
        save(productCategory);
        // 添加筛选属性
        List<Long> attributeIds = param.getProductAttributeIdList();
        if (CollUtils.isNotEmpty(attributeIds)) {
            // 批量添加
            insertAttributeList(productCategory.getId(), attributeIds);
        }
        return productCategory.getId();
    }

    /**
     * 修改分类
     * @param id 需要修改分类的ID
     * @param param 分类参数对象
     * @return 修改分类的ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long update(Long id, PmsProductCategoryParam param) {
        // 根据传入ID查询分类信息
        Validator.notNull(getById(id), "分类不存在");
        // 拷贝属性
        PmsProductCategory category = BeanUtils.copyProperties(param, PmsProductCategory.class);
        category.setId(id);
        // 设置分类等级
        setCategoryLevel(category);
        // 更新分类信息时，需要更新商品中分类名称
        pmsProductMapper.update(
                new PmsProduct().setProductCategoryName(param.getName()),
                new LambdaQueryWrapper<PmsProduct>().eq(PmsProduct::getProductCategoryId, id)
        );
        // 更新筛选属性
        List<Long> attributeIdList = param.getProductAttributeIdList();
        updateAttributeList(id, attributeIdList);
        // 修改分类信息
        updateById(category);
        return category.getId();
    }

    /**
     * 以树形结构获取所有商品分类
     * @return 商品分类树形列表
     */
    @Override
    public List<PmsProductCategoryNodeDTO> tree() {
        // 查询所有分类信息
        List<PmsProductCategory> allCategory = list();
        // 生成树形结构
        return allCategory.stream()
                .filter(item -> item.getParentId().equals(0L))
                .map(item -> covert(item, allCategory)).collect(Collectors.toList());
    }

    /**
     * 初始对象转化为节点对象
     * @param item 分类对象
     * @param allList 所有分类
     */
    private PmsProductCategoryNodeDTO covert(PmsProductCategory item, List<PmsProductCategory> allList) {
        // 创建节点对象
        return BeanUtils.copyProperties(
                item, PmsProductCategoryNodeDTO.class)
                // 设置子节点
                .setChildren(
                        allList.stream()
                                // 过滤出传入节点的所有子节点
                                .filter(subItem -> subItem.getParentId().equals(item.getId()))
                                // 转换为Map，递归调用找出子节点的所有子节点，最后转换为List
                                .map(subItem -> covert(subItem, allList)).collect(Collectors.toList())
                );
    }

    /**
     * 修改分类筛选属性
     * @param categoryId 分类ID
     * @param attributeIds 筛选属性ID列表
     */
    private void updateAttributeList(Long categoryId, List<Long> attributeIds) {
        // 清空筛选属性
        pmsProductCategoryAttributeRelationMapper.delete(
                new LambdaQueryWrapper<PmsProductCategoryAttributeRelation>()
                        .eq(PmsProductCategoryAttributeRelation::getProductCategoryId,
                                categoryId)
        );
        // 判断是否需要插入筛选属性
        if (CollUtils.isNotEmpty(attributeIds)) {
            insertAttributeList(categoryId, attributeIds);
        }
    }

    /**
     * 设置分类等级
     */
    private void setCategoryLevel(PmsProductCategory productCategory) {
        // 获取父级分类ID
        Long parentId = productCategory.getParentId();
        // 没有父级分类则为一级分类
        if (parentId == null || parentId == 0L) {
            productCategory.setLevel(0);
            productCategory.setParentId(0L);
            return;
        }
        // 有父级分类根据父级分类level设置
        PmsProductCategory parentCategory = getById(parentId);
        Validator.notNull(parentCategory, "父分类参数异常");
        productCategory.setLevel(parentCategory.getLevel() + 1);
    }

    /**
     * 批量插入分类筛选属性
     * @param categoryId 分类ID
     * @param attributeIds 筛选属性ID列表
     */
    private void insertAttributeList(Long categoryId, List<Long> attributeIds) {
        ArrayList<PmsProductCategoryAttributeRelation> relations = new ArrayList<>();
        Validator.notEmpty(attributeIds, "筛选属性为空");
        attributeIds.forEach(
                e -> relations.add(
                        new PmsProductCategoryAttributeRelation()
                                .setProductCategoryId(categoryId)
                                .setProductAttributeId(e))
        );
        pmsProductCategoryAttributeRelationMapper.insertList(relations);
    }


}
